package com.miao.im.support.handler;

import com.google.protobuf.InvalidProtocolBufferException;
import com.miao.im.common.Message;
import com.miao.im.server.session.SessionContext;
import com.miao.im.support.exception.BizException;
import com.miao.im.support.util.ProtoBufUtil;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

import java.lang.reflect.ParameterizedType;

/**
 * @Auther: miaoguoxin
 * @Date: 2021/3/1 14:13
 * @Description:
 */
@Slf4j
public abstract class AbstractMessageHandler<T extends com.google.protobuf.Message> implements IMessageHandler {

    protected abstract void doRead(T body, Message message);

    protected abstract Mono<Void> doDispatch(T body, Message message, SessionContext sessionContext);


    @Override
    public void read(Message message) {
        try {
            T body = this.getBody(message.getBody());
            if (body == null) {
                throw new InvalidProtocolBufferException("解析失败");
            }
            this.doRead(body, message);
        } catch (InvalidProtocolBufferException e) {
            log.error("消息解析失败", e);
            throw new BizException("消息解析失败！");
        }
    }

    @Override
    public Mono<Void> dispatch(Message message, SessionContext sessionContext) {
        return Mono.justOrEmpty(this.getBody(message.getBody()))
                .switchIfEmpty(Mono.error(new InvalidProtocolBufferException("解析失败")))
                .flatMap(body -> this.doDispatch(body, message, sessionContext));
    }

    private T getBody(byte[] bodyBytes) {
        try {
            Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            return ProtoBufUtil.parse(bodyBytes, type);
        } catch (Exception e) {
            log.error("转换protobuf异常:", e);
        }
        return null;
    }
}
